#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "HF_Lib.h"
#include "UTE_Defines.h"
#include "SCM_Lib.h"

BOOLEAN CheckFormat ( char *format );

  /*argv[0]="create"
   *argv[1]=όνομα-σχέσης
   *argv[2]=όνομα-πεδίου-1
   *argv[3]=φορμάτ-πεδίου-1
   *    .
   *    .
   *    .
   *argv[argc-2]=όνομα-πεδίου-Ν
   *argv[argc-1]=φορμάτ-πεδίου-ΝB
   *argv[argc]=NULL
   
    Ελέγχει τα ορίσματα της UT_create. Σε περίπτωση σωστών ορισματων επιστρέφει UTE_OK

   */

int SCM_create ( int argc, char *argv[] )
{
	int  i, j, scanDesc;
	relDesc record;

	/* Έλεγχος για σωστό αριθμό ορισμάτων. */
	

	if ( argv[argc] != NULL || argc % 2 != 0 )
	{
		return UTE_errno = UTE_CREATE;
	}

	/* Έλεγχος για το argv[0], αν είναι ίσο με "create". */

	if ( strcmp ( argv[0], "create" ) != 0 )
	{
		return  UTE_errno = UTE_CREATE;
	}

	/* Έλεγχος για αν τα attribute formats είναι σωστά
	 *και αν το μεγιστο μήκος για string είναι μικρότερο
	 *του MAXNAME.
	 */

	for ( i = 3; i < argc; i += 2 )
	{
		if ( CheckFormat ( argv[i] ) == FALSE )
		{
			return UTE_errno = UTE_CREATE;
		}
	}

	/* Έλεγχος αν κάποια στήλη του πίνακα που πρόκειτε να
	 *δημιουργήσουμε, έχει το ίδιο όνομα με κάποια άλλη
	 *απο τις στήλες του πίνακα αυτού.
	 */

	for ( i = 2; i < argc; i++ )
	{
			for ( j = i+ 1; j < argc; j++ )	
			{										
											
				if ( strcmp ( argv[i], argv[j] ) == 0 )
				{
					return UTE_errno = UTE_CREATE;
				}
			}
	}

	/* Έλεγχος αν το όνομα του πίνακα που πρόκειτε να δημιουργήσουμε υπάρχει ήδη στη βάση. */

	if ( ( scanDesc = HF_OpenFileScan ( relCatFd, sizeof(relDesc), 'c', MAXNAME, 0, EQUAL, argv[1] ) ) < 0 )
	{
		HF_PrintError("Error in SCM Create");			
		return UTE_errno = UTE_HF_ERROR;
	}

	if ( HF_FindNextRec ( scanDesc, (char *) &record) >= 0 )
	{
		HF_PrintError("Error in SCM Create");			
		return UTE_errno = UTE_HF_ERROR;
	}

	/* Έλεγχος αν κάποιο απο τα ονόματα ξεπερνάει το MAXNAME. */

	if ( strlen ( argv[1] ) > MAXNAME )
	{
		return UTE_errno = scanDesc;	
	}

	for ( i = 2; i < argc; i+= 2 )
	{
		if ( strlen ( argv[i] ) > MAXNAME )
		{									
			return UTE_CREATE;	
		}
	}
	
	HF_CloseFileScan(scanDesc);

	return UTE_errno = UTE_OK;	
}
/*argv[0]="buildindex"
   *argv[1]=όνομα-σχέσης
   *argv[2]=όνομα-πεδίου
   *argv[3]=NULL
   
   Ελέγχει τα ορίσματα της UT_buildIndex. Σε περίπτωση σωστών ορισμάτων επιστρέφει UTE_OK
   */

int SCM_buildIndex ( int argc, char *argv[] )
{
	int scanDesc, result, i;
	attrDesc record;

	if ( argc != 3 )
	{
		return UTE_errno = UTE_BUILD_INDEX;
	}

	/* Έλεγχος αν το όνομα του πίνακα ή το πεδίο ξεπερνάνε το MAXNAME. */

	for ( i = 1; i < 3; i++ )
	{
		if ( strlen ( argv[i] ) > MAXNAME )
		{
			return UTE_errno = UTE_BUILD_INDEX ;	
		}
	}

	/* Έλεγχος αν υπάρχει αυτό το πεδίο σε αυτή την σχέση.
	 *Ανοίγουμε scan για τον πίνακα attrCat, φέρνωτας όλα τα attributes
	 *του πίνακα με όνομα argv[1]. Μετά, αν δεν βρούμε στα αποτελέσματα
	 *το όνομα του πίνακα argv[1], σημαίνει πως δεν υπάρχει το πεδίο.
	 */

	if ( ( scanDesc = HF_OpenFileScan ( attrCatFd, sizeof(attrDesc), 'c', MAXNAME, 0, EQUAL, argv[1] ) ) < 0 )
	{
		HF_PrintError("Error in SCM Create index");			
		return UTE_errno = scanDesc;
	}

	while ( ( result = HF_FindNextRec ( scanDesc, (char *) &record) ) >= 0 )
	{
		if ( strcmp ( record.attrname, argv[2] ) == 0)
		{
			/* Αν όντως υπάρχει το πεδίο αυτό στον πίνακα επιστρέφουμε επιτυχή έλεγχο. */

			if ( ( UTE_errno = HF_CloseFileScan ( scanDesc ) ) < 0 )
			{
				HF_PrintError("Error in SCM Create index");	
				return UTE_errno;
			}

			/* Αν το attibute είναι ήδη ευρετηριασμένο, επιστροφή λαθους. */

			if ( record.indexed == 1 )
			{
				return UTE_errno = CFME_INDEXED;
			}

			return UTE_errno = UTE_OK;
		}
	}

	/* Αν τερματήσει η while σημαίνει πως δεν βρέθηκε το attribute σε αυτόν στον πίνακα,
	 *ή ο ίδιος πίνακας ή προκύψει κάποιο άλλο error απο την HF_FindNext επίπεδο. 
	 */

	HF_PrintError("Error in SCM Create index");	
	return UTE_errno = UTE_;
}


/*argv[0]="destroy"
 *argv[1]=όνομα-σχέσης
 *argv[2]=NULL
 
 Ελέγχει τα ορίσματα της UT_destroy. Σε περίπτωση σωστών ορισμα΄των επιστρέφει UTE_OK
 */

int SCM_destroy ( int argc, char *argv[] )
{
	int scanDesc;
	relDesc record;

	/* Έλεγχος γι αν το πρώτο όρισμα ειναι "destroy". */

	if ( strcmp ( argv[0], "destroy" ) != 0 )
	{
		return UTE_errno = UTE_DESTROY;
	}

	/* Έλεγχος αν μας ζητηθεί να καταστρέψουμε τον attrcat. */

	if ( strcmp ( argv[1], "attrcat" ) == 0 )
	{
		return UTE_errno = UTE_DESTROY;
	}

	/* Έλεγχος αν μας ζητηθεί να καταστρέψουμε τον relcat. */

	if ( strcmp ( argv[1], "relcat" ) == 0 )
	{
		return UTE_errno = UTE_DESTROY;
	}

	/* Έλεγχος για σωστό αριθμό ορισμάτων. */

	if ( argc != 2 )
	{
		return UTE_errno = UTE_DESTROY;
	}

	/* Έλεγχος για αν υπάρχει ο πίνακας με όνομα argv[1] 
	 *στη βάση.
	 */

	if ( ( scanDesc = HF_OpenFileScan ( relCatFd, sizeof(relDesc), 'c', MAXNAME, 0, EQUAL, argv[1] ) ) < 0 )
	{
		return UTE_errno = scanDesc;
	}

	if ( ( UTE_errno = HF_FindNextRec ( scanDesc, (char *) &record) ) < 0 )
	{
		return UTE_errno ;
	}
	
	if ( UTE_errno = HF_CloseFileScan(scanDesc) < 0 )
	{
		HF_PrintError("error in SCM destroy ");
		return UTE_errno = UTE_HF_ERROR;	
	}
		

	return UTE_errno = UTE_OK;
}


/* Ελέγχει τα ορίσματα της UT_print. Σε περίπτωση σωστών ορισμάτων επιστρέφει UTE_OK*/
int SCM_print ( char *relName )
{
	int scanDesc;
	relDesc record;

	/* Έλεγχος αν υπάρχει ο πίνακας προς εκτύπωση στη βάση. */

	if ( ( scanDesc = HF_OpenFileScan ( relCatFd, sizeof(relDesc), 'c', MAXNAME, 0, EQUAL, relName ) ) < 0 )
	{
		return UTE_errno = scanDesc;
	}

	if ( ( UTE_errno = HF_FindNextRec ( scanDesc, (char *) &record ) ) < 0 )
	{
		return UTE_errno;
	}
	else
	{
		return UTE_errno = UTE_OK;
	}
}

/*argv[0]="select"
    *argv[1]=όνομα-σχέσης-αποτελέσματος 
    *argv[2]=πλήθος-γνωρισμάτων-τα-οποία-προβάλλονται 
    *argv[3]=όνομα-προβαλλόμενης-σχέσης-1
    *argv[4]=όνομα-προβαλλόμενου-πεδίου-1
    *.
    *.
    *.
    *argv[argc-5]=όνομα-προβαλλόμενου-πεδίου-Ν
    *argv[argc-4]=όνομα-σχέσης-επιλογής 
    *argv[argc-3]=όνομα-πεδίου-επιλογής 
    *argv[argc-2]=τελεστής 
    *argv[argc-1]=τιμή 
    *argv[argc]=NULL

	H συνάρτηση τα format. Επιστρέφει TRUE αν είναι σωστά, αλλιώς FALSE.
	*/

BOOLEAN CheckFormat ( char *format )
{
	//char ch;

	//ch = format[0];
	//theloun to string 'i' na sigrinoume........
	printf("format[0] = %c\n", format[0]);
	printf("format = %s \n", format);

	if ( !strncmp(format,"'i",2) || !strncmp(format,"'f",2) || !strncmp(format,"'c",2))
	{
		/* Έλεγχος για αν το πρώτο γράμμα του format είναι σωστό. */
		
		if ( !strncmp(format,"'c",2) )
		{
			/* Αν πρόκειτε για string, πρέπει να ελέγχω αν το μέγιστο
			 *μήκος του είναι μικρότερο του MAXNAME. ( "cXXX" )
			 */

			//char *lenght;
			//*lenght= format[1];          ///????????? ayto ennoei???
			//int i;
			//i = atoi (format +2);
			//printf(" length = %d\n", i );
			return (atoi ( format+2 ) <= MAXNAME); 
		}
		else
		{	
			/* Αν πρόκειτε για αριθμό, ελέγχω αν είναι μεγέθους ένα 
			 *(πχ το iabc να μην το καταλάβει ως integer)
			 */

			return strlen ( format ) == 3;
		}
	}
	else
	{
		return FALSE;
	}
}
